﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
using namespace std;

// 实现⼀个ADD宏函数的常⻅问题
//#define ADD(int a, int b) return a + b;
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)
// 正确的宏实现
//#define ADD(a, b) ((a) + (b))
//// 为什么不能加分号?宏是替换机制的  ，在宏定义后面加分号的话就有问题了
//// 为什么要加外⾯的括号?   不加外面的括号这个优先级就有问题了
//// 为什么要加⾥⾯的括号?   同样是为了保持优先级
//
//int main()
//{
//	int ret = ADD(1, 2);//宏是替换机制的
//	cout << ret << endl;
//	;
//	cout << ADD(1, 2) << endl;     //第一个问题
//	cout << ADD(1, 2) * 5 << endl;    //第二个问题
//	int x = 1, y = 2;
//	ADD(x & y, x | y); // -> (x&y+x|y)  第三个问题
//	
//	return 0;
//}
/*
宏函数缺点很多，但是替换机制，调用时不用简历栈帧，提效，开销小
*/

//那么我们的祖师爷忍不了一点儿，就创建了这个inline


//inline  就是没有宏函数的坑，也不用建立栈帧，提效
//inline int Add(int x, int y)
//{
//	int ret = x + y;
//	return ret;
//}
//
///*
//宏是不能进行调试的，C++设计了inline目的就是替代C的宏函数
//*/
//int main()
//{
//	int rr = Add(1, 2);
//	cout << rr << endl;;
//	return 0;
//	
//}
//函数被编译以后是一对指令，需要存储起来执行

//第一句指令的地址就是函数的地址


//#ifndef NULL
//	#ifdef __cplusplus
//		#define NULL 0
//	#else
//		#define NULL ((void *)0)
//	#endif
//#endif

////下面两个函数构成函数重载
//void f(int x)
//{
//	cout << "f(int x)" << endl;
//}
//void f(int* ptr)
//{
//	cout << "f(int* ptr)" << endl;
//}
//int main()
//{
//	 
//	//f(0);//调用第一个
//	//f(NULL);//调用第二个
//	f(nullptr);//在c++中使用nullptr来定义空指针可以避免类型转换的问题
//
//	return 0;
//
//}
//class Stack
//{
//
//public:
//	//成员函数
//	void  Init(int n = 4)//给出一个缺省参数,缺省值默认给的是4
//	{
//		array = (int*)malloc(sizeof(int) * n);
//		if (nullptr == array)
//		{
//			perror("malloc fail!");
//			return;
//		}
//		capacity = n;
//		top = 0;
//	}
//	
//	void Push(int x)
//	{
//		//扩容
//		array[top++] = x;
//	}
//	int Top()
//	{
//		assert(top > 0);
//		return array[top - 1];
//	}
//	void Destroy()
//	{
//		free(array);
//		array = nullptr;
//		top = capacity = 0;
//	}
//
//private:
//	//成员变量
//	//栈
//	int* array;
//	size_t capacity;
//	size_t top;
//};
//
//struct Person//利用结构体也定义了一个类  那么类名就是类型
//{
//public://公有化
//	void Init(const char* name, int age, int tel)
//	{
//		strcpy(_name, name);//将name复制过去
//		_age = age;
//		_tel = tel;
//	}
//	void Print()
//	{
//		cout << "姓名：" << _name << endl;
//		cout << "年龄：" << _age << endl;
//		cout << "电话：" << _tel << endl;
//
//	}
//
//private://私有化
//	char _name[10];
//	int _age;
//	int _tel;
//};
//
//
////队列
//typedef struct QueueNode
//{
//	struct QueueNode* next;
//	int val;
//}QNode;
//
//typedef struct Queue
//{
//	QNode* head;
//	QNode* tail;
//	int size;
//}QU;
//
//void QueueInit(QU* q)
//{
//	q->head = nullptr;
//	q->tail = nullptr;
//	q->size = 0;
//}
////类名就是类型
//int main()
//{
//	Stack st1;//我们直接用这个类名当成类型来定义对象
//	//我们初始化的话直接就是类型加点再加函数名，那么我么家就调用了这个函数
//	st1.Init();
//	st1.Push(1);
//	st1.Push(2);
//	st1.Push(3);
//	st1.Push(4);
//
//	cout << st1.Top() << endl;
//
//	st1.Destroy();
//
//	Person p1;
//	p1.Init("张三",18,132);
//	p1.Print();
//
//
//	QU qu;
//	QueueInit(&qu);
//
//	return 0;
//}
//
////我们在这里定义public  公有的
////直到遇到下一个访问限定符，如果没有下一个访问限定符的话
////那么这个访问限定符到};这个中间的空间都是外界能够进行访问的
//
////我们在函数后面加上private，那么这些函数就是公有的
////那么private到};中间的就是私有的
//
//
////一般来说的话成员函数一般是公有的
////成员的变量一般是私有的
//
////那么到这里我们就真正定义出了一个类
//
////类中有成员变量也有成员函数
//
////我们现在是能对类里面的的函数进行访问的，但是不能对类里面的变量成员进行访问，因为这个是我们的私有的
//
////我们能用struct来定义类，但是我们还是推荐用class
//
//
////那么我们通过这种队列的案例我们发现在C++中
////我们的struct既能像c语言一样用struct来定义结构体,也能像C++一样用struct来定义类
//
//
////在类里面定义成员函数默认是内联函数  前面没有加inline那么默认也加了inline
//
//
////struct兼容C语言的用法，又有C++的用法
//
////那么struct用C++的用法的时候和class有什么区别呢？



///////////////////////////////////////////////////
 
//class QUeue
//{
//public:
//	void Init()
//	{
//
//	}
//};

//#include"Stack.h"
//int main()
//{
//	Stack st;//  类中的栈   定义一个栈
//	st.Init();//栈的初始化
//	return 0;
//}
//这个就是标准的类的声明和定义分离
//我们在Stack.cpp文件中指定我们要查找的函数，前面带上指定的类域
//那么编译器就会到指定的类域进行搜索

//函数声明定义分离的时候我们要指定类域